package com.ipncinf.camera;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class CameraUtils {
	public static final int CAMERA_DEFAULT_PORT = 80; // 默认摄像头端口
	private static final int CAMERA_DETECT_TIMEOUT = 100; // 探测摄像头超时时间
	public static final String LOCAL_CAMERA_DISPLAY = "局域网";
	public static final String REMOTE_CAMERA_DISPLAY = "广域网";

	/**
	 * 调用摄像头的CGI接口
	 */
	public static Map<String, Object> invokeCamera(String cameraUrl) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			URL url = new URL(dealStringFormat(cameraUrl));
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(2000);
			conn.setReadTimeout(2000);
			conn.setDoOutput(true);
			OutputStreamWriter os = new OutputStreamWriter(
					conn.getOutputStream(), "ISO8859-1");
			os.flush();
			conn.connect();
			InputStream is = conn.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			String line = "";
			while ((line = br.readLine()) != null) {
				if (CommUtils.isValidStr(line) && line.indexOf("=") != -1
						&& line.indexOf(";") != -1) {
					line = line.replace("var ", "").replace(";", "");
					String key = line.substring(0, line.indexOf("="));
					String value = line.substring(line.indexOf("=") + 1);
					if ("''".equals(value) || "\"\"".equals(value)) {
						value = "";
					}
					if (line.indexOf("new") != -1) {
						// TODO 处理var abc=new Array();这种情况
					} else {
						map.put(key, value);
					}
				}
			}
			if (br != null) {
				br.close();
			}
			if (is != null) {
				is.close();
			}
			if (os != null) {
				os.close();
			}
			if (conn != null) {
				conn.disconnect();
			}
		} catch (Exception e) {
			return null;
		}
		return map;
	}

	public static void main(String[] args) {
		detectLocalAreaNetworkCameras();
	}

	/**
	 * 摄像头拍照
	 */
	public static void snapshotCamera(String cameraUrl, String savePath) {
		if (cameraUrl == null || savePath == null) {
			throw new RuntimeException("拍照参数有误");
		}
		HttpClient httpClient = new HttpClient();
		GetMethod getMethod = new GetMethod(dealStringFormat(cameraUrl));
		// 使用系统提供的默认的恢复策略
		getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
				new DefaultHttpMethodRetryHandler());
		try {
			int statusCode = httpClient.executeMethod(getMethod);
			if (statusCode != HttpStatus.SC_OK) {
				throw new RuntimeException("拍照出错");
			}
			byte[] responseBody = getMethod.getResponseBody();
			String disposition = getMethod.getResponseHeader(
					"Content-disposition").getValue();
			String fileName = disposition
					.substring(
							disposition.indexOf("filename=")
									+ "filename=".length() + 1,
							disposition.length() - 1);
			OutputStream serverout = new FileOutputStream(savePath + fileName);
			serverout.write(responseBody);
			serverout.flush();
			serverout.close();
		} catch (Exception e) {
			throw new RuntimeException("拍照出错");
		} finally {
			// 释放连接
			getMethod.releaseConnection();
		}
	}

	public static String dealStringFormat(String field) {
		if (CommUtils.isValidStr(field)) {
			field = field.replaceAll(" ", "%20").replaceAll("\\+", "%2B")
					.replaceAll("\\#", "%23");
			if (field.indexOf("http") == -1) {
				field = "http://" + field;
			}
		}
		return field;
	}

	/**
	 * 探测局域网内摄像头
	 */
	public static List<String> detectLocalAreaNetworkCameras() {
		List<String> list = new ArrayList<String>();
		try {
			InetAddress inet = InetAddress.getLocalHost();
			String hostip = inet.getHostAddress();
			String part1 = hostip.substring(0, hostip.lastIndexOf(".") + 1);
			String part2 = hostip.substring(hostip.lastIndexOf(".") + 1);
			int lastPartOfIP = Integer.parseInt(part2);
			StringBuilder sb = new StringBuilder();

			for (int i = 1; i <= 255; i++) {
				if (lastPartOfIP != i) {
					sb.append("http://").append(part1).append(i).append(":")
							.append(CAMERA_DEFAULT_PORT);

					if (detectOneTime(sb.toString())) {
						list.add(part1 + i);
					}

					sb.delete(0, sb.length());
				}
			}
		} catch (Exception e) {
			return null;
		}
		return list;
	}

	/**
	 * 探测一次
	 */
	private static boolean detectOneTime(String cameraUrl) {
		try {
			URL url = new URL(cameraUrl);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setConnectTimeout(CAMERA_DETECT_TIMEOUT);
			conn.setReadTimeout(CAMERA_DETECT_TIMEOUT);
			conn.setDoOutput(false);
			conn.connect();
			if (conn != null) {
				conn.disconnect();
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}
}
